package com.ysxn.util;

import java.io.UnsupportedEncodingException;

/**
 * 16进制数操作工具
 * @author stronghill
 *
 */
public class HexTool {
	/**
	 * 16进制字节流转BCD码数字
	 * data=04 32 35 20 60，count=4，pointx=0, ret="0.04323520"; pointx=1,ret="0.4323520"; pointx=2, ret="4.323520" 
	 * @param data 字节流
	 * @param count 字节流长度
	 * @param pointx 小数点位置，0表示小数点在第一位的前面
	 * @return 转换后的数字的字符串，去掉了整数部分前面的0，如果小数点在末尾，则不输出;失败返回-1;
	 */
	public static String byteToBCDStr(byte[] data, int count, int pointx){
		String ret = "";
		for(int i = 0; i < count; i++){
			int dd = data[i];
			if (dd < 0){
				dd = 0x100 + dd;
			}
			int a = dd % 16;
			if(a < 0 || a > 9){		
				return "";
			}
			int b = (dd % 256) / 16;
			if(b < 0 || b > 9){		
				return "";
			}
			ret += String.format("%d%d", b, a);
		}
		if(pointx == 0){
			ret = "0." + ret;
			return ret;
		}else if(pointx > 0 && pointx < count*2){
			ret = ret.substring(0, pointx) +  "." + ret.substring(pointx, ret.length());
			while(ret.charAt(0) == '0' && ret.charAt(1) != '.'){
				ret = ret.substring(1);
			}
		}else if(pointx >= count*2){
			while(ret.charAt(0) == '0' && ret.length() > 1){
				ret = ret.substring(1);
			}
		}else{
			return "-1";
		}
		return ret;
	}
	/**
	 * 16进制字节流转BCD码数字 保留0
	 * data=04 32 35 20 60，count=4，pointx=0, ret="0.04323520"; pointx=1,ret="0.4323520"; pointx=2, ret="4.323520" 
	 * @param data 字节流
	 * @param count 字节流长度
	 * @param pointx 小数点位置，0表示小数点在第一位的前面
	 * @return 转换后的数字的字符串，去掉了整数部分前面的0，如果小数点在末尾，则不输出;失败返回-1;
	 */
	public static String byteToBCDStrWith0(byte[] data, int count, int pointx){
		String ret = "";
		for(int i = 0; i < count; i++){
			int dd = data[i];
			if (dd < 0){
				dd = 0x100 + dd;
			}
			int a = dd % 16;
			if(a < 0 || a > 9){		
				return "";
			}
			int b = (dd % 256) / 16;
			if(b < 0 || b > 9){		
				return "";
			}
			ret += String.format("%d%d", b, a);
		}
		if(pointx == 0){
			ret = "0." + ret;
			return ret;
		}else if(pointx > 0 && pointx < count*2){
			ret = ret.substring(0, pointx) +  "." + ret.substring(pointx, ret.length());
			while(ret.charAt(0) == '0' && ret.charAt(1) != '.'){
				ret = ret.substring(1);
			}
		}else if(pointx >= count*2){
			return ret;
		}else{
			return "-1";
		}
		return ret;
	}
	
	/**
	 * 求字节流的校验和
	 * @param data 需要求和的字节流
	 * @param from 求和的起始字节 从0开始
	 * @param to 求和的终止字节
	 * @param sumlen 和的字节数
	 * @return
	 */
	public static byte[] getSum(byte[] data, int from, int to, int sumlen){
		byte[] ret = new byte[sumlen];
		int sum = 0;
		for(int i = from; i <= to; i++){
			sum = sum + ((256 + data[i]) % 256);
		}
		for(int i = 0; i < sumlen; i++){
			ret[i] = (byte) (sum % 256);
			sum = sum / 256;
		}
		return ret;
	}
	
	/**
	 * 将byte[]转换成16进程数字组成的字符串， 用sep分割
	 * data=0d 32 35 2f 60 ,sep=",",ret=0d,32,35,2f,60,
	 * @param data 源串
	 * @param sep 分割符
	 * @return
	 */
	public static String byteToHex(byte[] data, String sep){
		String ret = "";
		for(int i = 0; i < data.length; i++){
			ret += String.format("%1$02x", data[i]) + sep;
		}
		return ret;
	}
	
	/**
	 * 将byte[from] 到 byte[to] 转换成16进程数字组成的字符串， 用sep分割
	 * data=0d 32 35 2f 60 ,from=1,to=2,sep=",",ret=32,35,
	 * @param data 源串
	 * @param from 起始字节
	 * @param to 结束字节
	 * @param sep 分割符
	 * @return
	 */
	public static String byteToHexPart(byte[] data, int from, int to, String sep){
		String ret = "";
		for(int i = from; i <= to; i++){
			ret += String.format("%1$02x", data[i]) + sep;
		}
		return ret;
	}
	
	/**
	 * 将byte[]的可见字符转换成字符串
	 * data=32 35 37 47 ,from=0, to=3,ret="257G",
	 * @param data
	 * @param sep
	 * @return
	 */
	public static String byteToStr(byte[] data, int from, int to){
		String ret = null;
		byte[] aa = new byte[to -from + 1];
		for(int i = from; i <= to; i++){
			aa[i- from] = data[i];
		}
		
		try {
			ret = new String(aa, "GBK");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return ret;
	}
	/**
	 * 将16进制串转为byte流
	 * hexString="0a,0c,65",ret=0a 0c 65
	 * @param hexString 16进制串
	 * @param sep 分割符
	 * @return  单个byte
	 */
	public static byte[] hexStringToBytes(String hexString, char sep) {
		//char[] str = 
			//hexString.charAt(index)
		String sst = hexString + " ";
		byte[] ret = new byte[sst.length() / 3];
		for(int i = 0; i < hexString.length(); i = i + 3){
			char ci0 = hexString.charAt(i);
			char ci1 = hexString.charAt(i + 1);
			byte bt = 0x0;
			if(ci0 >= '0' && ci0 <='9'){
				bt = (byte)((ci0 - 0x30) * 16);
			}else if(ci0 >= 'a' && ci0 <= 'f'){
				bt = (byte)((ci0 - 'a' + 10) * 16);
			}else if(ci0 >= 'A' && ci0 <= 'F'){
				bt = (byte)((ci0 - 'A' + 10) * 16);
			}else{
				return null;
			}
			
			if(ci1 >= '0' && ci1 <='9'){
				bt += (byte)(ci1 - 0x30);
			}else if(ci1 >= 'a' && ci1 <= 'f'){
				bt += (byte)(ci1 - 'a' + 10);
			}else if(ci1 >= 'A' && ci1 <= 'F'){
				bt += (byte)(ci1 - 'A' + 10);
			}else{
				return null;
			}
			ret[i / 3] = bt;
		}

		return ret;

	}
	
	/**
	 * 计算crc16校验值
	 * @param data 源串
	 * @param from 起始字节 从0开始
	 * @param to 终止字节
	 * @return 两字节的校验值
	 */
	public static byte[] crc16(byte[] data, int from, int to) {
		int[] table = { 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280,
				0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481,
				0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81,
				0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880,
				0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81,
				0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80,
				0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680,
				0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081,
				0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281,
				0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480,
				0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80,
				0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881,
				0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80,
				0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81,
				0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681,
				0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080,
				0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281,
				0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480,
				0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80,
				0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881,
				0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80,
				0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81,
				0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681,
				0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080,
				0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280,
				0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481,
				0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81,
				0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880,
				0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81,
				0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80,
				0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680,
				0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081,
				0x4040, };
		
		

		int crc = 0x0000;
		for (int i = from; i <=to; i++ ) {
			crc = (crc >>> 8) ^ table[(crc ^ data[i]) & 0xff];
		}
		
		byte[] ret = new byte[2];
		ret[0] = (byte) (crc % 256);
		ret[1] = (byte) (crc / 256);
		
		return ret;
	}
	/**
	 * 将byte串的一部分转成十进制数输出
	 * data=32 35 37 47 ,from=0, to=1, fx=true，ret=50*256+53="12883",
	 * @param data 源串
	 * @param from 起始字节
	 * @param to 结束字节
	 * @param fx true表示高位在前，false表示低位在前
	 * @return
	 */
	public static String byteToDec(byte[] data, int from, int to, boolean fx){
		long ret = 0;
		//Integer.valueOf(s)
		//byte[] rd = new byte[to - from + 1];
		int ntmp = 0;
		if(fx){
			for(int i = from; i <= to; i++){
				ntmp = (data[i] + 256) % 256;
				ret += ntmp * java.lang.Math.pow(256, to - i);
				//rd[i - from] = data[i];
			}
		}else{
			for(int i = to; i >= from; i--){
				ntmp = (data[i] + 256) % 256;
				ret += ntmp * java.lang.Math.pow(256, i - from);
				//rd[to - i] = data[i];
			}
		}
		//ret = (long)rd;
		return String.valueOf(ret);
	}
	
	/**
	 * 将byte串的一部分转成十进制数输出
	 * data=32 35 37 47 ,from=0, to=1, fx=true，ret=50*256+53="12883",
	 * @param data 源串
	 * @param from 起始字节
	 * @param to 结束字节
	 * @param fx true表示高位在前，false表示低位在前
	 * @return
	 */
	public static int byteToDecInt(byte[] data, int from, int to, boolean fx){
		int ret = 0;
		//Integer.valueOf(s)
		//byte[] rd = new byte[to - from + 1];
		int ntmp = 0;
		if(fx){
			for(int i = from; i <= to; i++){
				ntmp = (data[i] + 256) % 256;
				ret += ntmp * java.lang.Math.pow(256, to - i);
				//rd[i - from] = data[i];
			}
		}else{
			for(int i = to; i >= from; i--){
				ntmp = (data[i] + 256) % 256;
				ret += ntmp * java.lang.Math.pow(256, i - from);
				//rd[to - i] = data[i];
			}
		}
		//ret = (long)rd;
		return ret;
	}
	/**
	 * 字符串转byte【】
	 * @param strargs
	 */
	public static byte[] StringTohex(String strargs) {	
		String[] hexStr = { "0", "1", "2", "3", "4", "5", "6", "7", "8","9", "A", "B", "C", "D", "E", "F" };
		// 这里还可以做些判断，比如传进来的数字是否都是0和1	
		
		int intstrargs=Integer.parseInt(strargs);
		String binary=Integer.toBinaryString(intstrargs);
		
		int length = binary.length();
		
		 
		int temp = length % 8;
		// 每四位2进制数字对应一位16进制数字		// 补足4位		
		if (temp != 0) {
			for (int i = 0; i < 8 - temp; i++) {
				binary = "0" + binary;
			}
		} // 重新计算长度		
		length = binary.length();
		 byte [] rt = new byte[ length/4];
		 StringBuffer sp=new StringBuffer();
		// 每4个二进制数为一组进行计算		
		for (int i = 0; i < length / 4; i++) {
			int num = 0; // 将4个二进制数转成整数		
			for (int j = i * 4; j < i * 4 + 4; j++) {
				num <<= 1;// 左移			
				num |= (binary.charAt(j) - '0');// 或运算		
			}
			// 直接找到该整数对应的16进制，这里不用switch来做		
			sp.append(hexStr[num]); 
			if(i%2==1){
				sp.append(",");
			}
			
		}
		
		rt=HexTool.hexStringToBytes(sp.toString(), ',');
		byte  [] rts =null;
		if(rt.length==1){
			rts=new byte [2];
			rts[0]=0;
			rts[1]=rt[0];
		}else{
			rts=new byte [2];
			rts[0]=rt[0];
			rts[1]=rt[1];	
		}
		return rts;

	}
	
	public static byte[] hexStringToByte(String hex) {
	    int len = (hex.length() / 2);
	    byte[] result = new byte[len];
	    hex = hex.toUpperCase();
	    char[] achar = hex.toCharArray();
	    for (int i = 0; i < len; i++) {
	     int pos = i * 2;
	     result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
	    }
	    return result;
	}
	private static byte toByte(char c) {
	    byte b = (byte) "0123456789ABCDEF".indexOf(c);
	    return b;
	}
	/**
	 * String s = "20130605163332"; 
	 * byte[]=0x20,0x13,0x06,0x05.......
	 * @param asc
	 * @return
	 */
	public static byte[] str2Bcd(String asc) {
	    int len = asc.length();
	    int mod = len % 2;

	    if (mod != 0) {
	     asc = "0" + asc;
	     len = asc.length();
	    }

	    byte abt[] = new byte[len];
	    if (len >= 2) {
	     len = len / 2;
	    }

	    byte bbt[] = new byte[len];
	    abt = asc.getBytes();
	    int j, k;

	    for (int p = 0; p < asc.length()/2; p++) {
	     if ( (abt[2 * p] >= '0') && (abt[2 * p] <= '9')) {
	      j = abt[2 * p] - '0';
	     } else if ( (abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) {
	      j = abt[2 * p] - 'a' + 0x0a;
	     } else {
	      j = abt[2 * p] - 'A' + 0x0a;
	     }

	     if ( (abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) {
	      k = abt[2 * p + 1] - '0';
	     } else if ( (abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) {
	      k = abt[2 * p + 1] - 'a' + 0x0a;
	     }else {
	      k = abt[2 * p + 1] - 'A' + 0x0a;
	     }

	     int a = (j << 4) + k;
	     byte b = (byte) a;
	     bbt[p] = b;
	    }
	    return bbt;
	}

	public static  byte[] getSumH (byte data[],int from, int to, int sumlen) 
	{ 
		byte [] rt = new byte [sumlen];
	 //char a[]="$GPGGA,085014.955,2839.2050,N,11549.5721,E,1,04,03.6,76.6,M,-6.2,M,,*4C";
	 int result=0;

	 for(int i =from;i<to;i++)
	 {
	  result^=data[i];
	 }
	 rt[0] =(byte) result;
	
	 System.out.println("result="+String.format("%x\n",result)); 
	 return rt;
	} 
	public  static byte[] intToByteArray(int number, int length)   
	    {   
	        byte[] byteArray = new byte[length];    
	  
	       int shiftNum = 0;   // 移位数   
	        for(int i=0; i<length; i++)   
	        {   
	            shiftNum = (length-i-1)*8;   
	            byteArray[i] = (byte)((number >> shiftNum) & 0xFF);   
	        }   
	        return byteArray;   
	    }  
	/**
	 * 字符串循环右移一位A5 99 95 17 99 输出9A 59 99 51 79
	 * @param msg
	 * @return
	 */
	public static String strToRight1(String msg){
		
		char [] sd = msg.toCharArray();
		char [] asd = new char[sd.length];
		for(int i = 0 ;i <sd.length;i++){
			if(i==sd.length-1){
			asd[0]=sd[i];
			}else{
				asd[i+1]=sd[i];
			}
		}
		return new String (asd);
	}

}
